package service

import (
	"context"
	"fmt"
	v1 "gin-vben-admin/api/v1"
	"gin-vben-admin/api/v1/errcode"
	"gin-vben-admin/internal/model"
	"gin-vben-admin/internal/repository"
	"strings"
)

type SysDeptService interface {
	GetTreeListByPid(ctx context.Context, pid int64) (treeModels []*model.SysDept, err error)
	Create(ctx context.Context, req *v1.SysDeptCreateReq) error
	Update(ctx context.Context, req *v1.SysDeptUpdateReq) (err error)
	Delete(ctx context.Context, deptId int64) (err error)
}

func NewSysDeptService(service *Service, deptRepo repository.SysDeptRepository) SysDeptService {
	return &sysDeptService{
		deptRepo: deptRepo,
		Service:  service,
	}
}

type sysDeptService struct {
	deptRepo repository.SysDeptRepository
	*Service
}

// Create 添加部门
func (s *sysDeptService) Create(ctx context.Context, req *v1.SysDeptCreateReq) error {
	m := model.SysDept{}
	m.DeptName = req.DeptName
	m.Sort = req.Sort
	m.Status = req.Status
	m.ParentId = req.ParentId
	m.Remark = req.Remark
	m.CreateBy = req.AuthId
	m.UpdateBy = req.AuthId
	//顶级部门
	if m.ParentId != 0 {
		pModel, err := s.deptRepo.GetById(ctx, m.ParentId)
		if err != nil {
			return errcode.ErrBadRequestParams.New("上级部门选择错误")
		}
		m.IdPath = fmt.Sprintf("%s%d/", pModel.IdPath, pModel.DeptId)
	} else {
		m.IdPath = "/0/"
	}
	return s.deptRepo.Create(ctx, &m)
}

// GetTreeListByPid 根据parentId获取子菜单树状结构
func (s *sysDeptService) GetTreeListByPid(ctx context.Context, pid int64) (treeModels []*model.SysDept, err error) {
	var list []*model.SysDept
	list, err = s.deptRepo.GetListByPid(ctx, pid)
	if err != nil {
		return
	}
	return s.genTreeList(list, pid), nil
}

func (s *sysDeptService) Delete(ctx context.Context, deptId int64) (err error) {
	if deptId == 0 {
		return errcode.ErrBadRequest
	}
	//事物处理
	return s.tm.Transaction(ctx, func(ctx context.Context) error {
		total, err := s.deptRepo.GetCountByPid(ctx, deptId)
		fmt.Println(total, err)
		if err != nil {
			return err
		}
		if total > 0 {
			return errcode.ErrBadRequest.New("请先将其子部门删除后方能删除此部门")
		}
		return s.deptRepo.Delete(ctx, deptId)
	})
}

func (s *sysDeptService) Update(ctx context.Context, req *v1.SysDeptUpdateReq) (err error) {
	var m *model.SysDept
	m, err = s.deptRepo.GetById(ctx, req.DeptId)
	if err != nil {
		return
	}
	m.DeptName = req.DeptName
	m.Sort = req.Sort
	m.Status = req.Status
	m.ParentId = req.ParentId
	m.Remark = req.Remark
	m.UpdateBy = req.AuthId

	if m.ParentId == m.DeptId {
		return errcode.ErrBadRequestParams.New("上级部门选择错误")
	}
	//顶级部门
	oldS := fmt.Sprintf("%s%d/", m.IdPath, m.DeptId)
	if m.ParentId != 0 {
		pModel, err := s.deptRepo.GetById(ctx, m.ParentId)
		if err != nil {
			return errcode.ErrBadRequestParams.New("上级部门选择错误")
		}
		if strings.Contains(pModel.IdPath, fmt.Sprintf("/%d/", m.DeptId)) {
			return errcode.ErrBadRequestParams.New("上级部门选择错误")
		}
		m.IdPath = fmt.Sprintf("%s%d/", pModel.IdPath, pModel.DeptId)
	} else {
		m.IdPath = "/0/"
	}
	newS := fmt.Sprintf("%s%d/", m.IdPath, m.DeptId)

	return s.tm.Transaction(ctx, func(ctx context.Context) error {
		err := s.deptRepo.Update(ctx, m, "dept_name", "sort", "status", "parent_id", "remark", "update_by", "id_path")
		if err != nil {
			return err
		}
		return s.deptRepo.UpdateIdPath(ctx, oldS, newS)
	})
}

// genTreeList 根据菜单列表生成树状菜单
func (s *sysDeptService) genTreeList(list []*model.SysDept, parentId int64) []*model.SysDept {
	res := make([]*model.SysDept, 0)
	for _, v := range list {
		if v.ParentId == parentId {
			v.Children = s.genTreeList(list, v.DeptId)
			res = append(res, v)
		}
	}
	return res
}
